/*
 * @Author: 吴世扬 18368095041@163.com
 * @Date: 2025-02-19 16:41:07
 * @LastEditors: 吴世扬 18368095041@163.com
 * @LastEditTime: 2025-02-25 17:30:11
 * @FilePath: /vue3-admin-server/src/services/role.service.ts
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, DataSource } from 'typeorm';

import { RoleEntity } from 'src/entities/role.entity';
import { RoleDTO, RoleListDTO } from 'src/common/dto/role';
import { arrayToTreeByField } from 'src/common/utils';

@Injectable()
export class RoleService {
    constructor(
        @InjectRepository(RoleEntity)
        private readonly roleRepository: Repository<RoleEntity>,
        private readonly dataSource: DataSource // 添加: 注入 DataSource
    ) {}

    async readList(
        roleListDTO: RoleListDTO
    ): Promise<VO.PageDataVO<VO.RoleVO>> {
        const { current, size, sortList, name, ...rest } = roleListDTO;

        // 构建查询
        const queryBuilder = this.roleRepository
            .createQueryBuilder('role')
            .where(rest);

        // 添加 name 的模糊搜索条件
        if (name) {
            queryBuilder.andWhere('role.name LIKE :name', {
                name: `%${name}%`
            });
        }

        // 应用排序
        if (sortList && sortList.length > 0) {
            sortList.forEach((sort) => {
                queryBuilder.addOrderBy(
                    `role.${sort.column}`,
                    sort.order.toUpperCase() as 'ASC' | 'DESC'
                );
            });
        }

        // 获取总数
        const total = await queryBuilder.getCount();

        // 获取分页数据
        const roleList = await queryBuilder
            .skip((current - 1) * size)
            .take(size)
            .getMany();

        return {
            current: roleListDTO.current,
            size: roleListDTO.size,
            total,
            records: roleList
        };
    }

    async readAll(): Promise<VO.RoleVO[]> {
        const queryBuilder = this.roleRepository.createQueryBuilder('role');
        return queryBuilder.getMany();
    }

    async readDetail(id: number): Promise<VO.RoleVO | null> {
        const queryBuilder = this.roleRepository
            .createQueryBuilder('role')
            .leftJoinAndSelect('role.menus', 'menu')
            .where({
                id
            });
        const data = await queryBuilder.getOne();
        if (!data) return null;
        const { menus, ...role } = data;
        return {
            ...role,
            menuTree: arrayToTreeByField(
                menus,
                'id',
                'parentId',
                (a, b) => b.sortWeight - a.sortWeight
            )
        };
    }

    async save(roleDTO: RoleDTO) {
        let result: number | Error;
        const queryRunner = this.dataSource.createQueryRunner(); // 修改: 使用 DataSource 创建 QueryRunner

        try {
            await queryRunner.connect();
            await queryRunner.startTransaction();

            const { id, menuIds, ...rest } = roleDTO;
            if (id) {
                await queryRunner.manager
                    .createQueryBuilder()
                    .update(RoleEntity, rest)
                    .where('id = :id', { id })
                    .execute();
                result = id;
            } else {
                const { identifiers } = await queryRunner.manager
                    .createQueryBuilder()
                    .insert()
                    .into(RoleEntity)
                    .values(rest)
                    .execute();
                result = identifiers[0].id as number;
            }
            const role = await queryRunner.manager
                .createQueryBuilder(RoleEntity, 'role')
                .where({
                    id: result
                })
                .leftJoinAndSelect('role.menus', 'menu')
                .getOne();
            await queryRunner.manager
                .createQueryBuilder()
                .relation(RoleEntity, 'menus')
                .of(id)
                .remove(role?.menus.map((menu) => menu.id));

            // 直接设置新的 menus 关联
            if (menuIds && menuIds.length > 0) {
                await queryRunner.manager
                    .createQueryBuilder()
                    .relation(RoleEntity, 'menus')
                    .of(result)
                    .add(menuIds);
            }

            await queryRunner.commitTransaction();
            return Promise.resolve(result);
        } catch (e) {
            await queryRunner.rollbackTransaction();
            result = e as Error;
            return Promise.reject(result);
        } finally {
            await queryRunner.release();
        }
    }

    async delete(id: number): Promise<true | Error> {
        const queryRunner = this.dataSource.createQueryRunner(); // 修改: 使用 DataSource 创建 QueryRunner
        try {
            await queryRunner.connect();
            await queryRunner.startTransaction();
            const queryBuilder = queryRunner.manager.createQueryBuilder(
                RoleEntity,
                'role'
            );
            const role = await queryBuilder
                .where({
                    id
                })
                .leftJoinAndSelect('role.menus', 'menu')
                .getOne();
            await queryBuilder
                .relation(RoleEntity, 'menus')
                .of(id)
                .remove(role?.menus.map((menu) => menu.id));
            await queryBuilder
                .delete()
                .from(RoleEntity)
                .where('id = :id', { id })
                .execute();
            await queryRunner.commitTransaction();
            return Promise.resolve(true);
        } catch (e) {
            await queryRunner.rollbackTransaction();
            return Promise.reject(e as Error);
        } finally {
            await queryRunner.release();
        }
    }
}
